--[[
	Name: HookLib-1.0
]]

local MAJOR_VERSION = "HookLib-1.0"
local MINOR_VERSION = "$Revision: 1 $"

-- Credits to shines77 (Guozi)
zUI.hooklib = {}
zUI.hooklib.modules = {}

-- load zUI environment
setfenv(1, zUI:GetEnvironment())

local is_debug = false

--[[---------------------------------------------------------------------------------
	Create the library object
----------------------------------------------------------------------------------]]

local table_setn
do
	local version = GetBuildInfo()
	if string.find(version, "^2%.") then
		-- 2.0.0
		table_setn = function() end
	else
		table_setn = table.setn
	end
end

--[[---------------------------------------------------------------------------------
	Library Definitions
----------------------------------------------------------------------------------]]

local protFuncs = {
	CameraOrSelectOrMoveStart = true, 	CameraOrSelectOrMoveStop = true,
	TurnOrActionStart = true,			TurnOrActionStop = true,
	PitchUpStart = true,				PitchUpStop = true,
	PitchDownStart = true,				PitchDownStop = true,
	MoveBackwardStart = true,			MoveBackwardStop = true,
	MoveForwardStart = true,			MoveForwardStop = true,
	Jump = true,						StrafeLeftStart = true,
	StrafeLeftStop = true,				StrafeRightStart = true,
	StrafeRightStop = true,				ToggleMouseMove = true,
	ToggleRun = true,					TurnLeftStart = true,
	TurnLeftStop = true,				TurnRightStart = true,
	TurnRightStop = true,
}

local _G = getfenv(0)

--[[---------------------------------------------------------------------------------
	Private definitions (Not exposed)
----------------------------------------------------------------------------------]]

--[[----------------------------------------------------------------------
	_debug - Internal Method
-------------------------------------------------------------------------]]
local function to_string(str)
    if str ~= nil then
        if type(str) == "table" then
            return "<table>";
        elseif type(str) == "function" then
            return "<function>";
        else
            return tostring(str)
        end
    else
        return "<nil>"
    end
end

local function print(text)
	if DEFAULT_CHAT_FRAME then
		DEFAULT_CHAT_FRAME:AddMessage(text)
	end
end

local function _debug(self, msg)
	local name = self.modules[1].name
	if name then
		print(string.format("[%s]: %s", name, msg))
	else
		print(msg)
	end
end

local function _error(fmt, ...)
	local msg = string.format(fmt, unpack(arg))
	print(msg)
end

local function dump_obj(msg)
    if (not is_debug) then return ""; end
    local txt = "";
    if type(msg) == "table" then
        local total = 0;
        for k, v in pairs(msg) do
            txt = txt.."  ['"..k.."']: "..dump_obj(v).."\n";
            total = total + 1;
        end
        if (total == 0) then
            txt = "<empty table>"
        end
    elseif type(msg) == "function" then
        txt = "<function>";
    elseif type(msg) == "nil" then
        txt = "<nil>";
    else
        txt = tostring(msg);
    end
    return txt;
end

local function dump(msg)
    local txt = dump_obj(msg);
    print(txt);
end

local new, del
do
	local list = setmetatable({}, {__mode = "k"})
	function new()
		local t = next(list)
		if not t then
			return {}
		end
		list[t] = nil
		return t
	end

	function del(t)
		setmetatable(t, nil)
		table_setn(t, 0)
		for k in pairs(t) do
			t[k] = nil
		end
		list[t] = true
	end
end

local origFuncMetatable = {
	__call = function(self, a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
		--print("a1 = "..to_string(a1))
		--print("a2 = "..to_string(a2))
		--print("a3 = "..to_string(a3))
		return self.orig(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
	end
}

local origMethodMetatable = {
	__call = function(self, a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
		return self.orig(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
	end
}

--[[----------------------------------------------------------------------
	_getFunctionHook - internal method
-------------------------------------------------------------------------]]
local function _getFunctionHook(self, name, func, handler, orig, pre_hooks)
	local module_ = self.modules[name]
	if type(handler) == "string" then
		-- The handler is a method, need to self it
		return function(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
			if module_.actives[orig] then
				if (pre_hooks == nil) then
					-- nil: pre_hooks
					self[handler](self, a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
					return orig(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
				else
					-- true: post_hooks
					if (pre_hooks == true) then
						orig(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
					end
					return self[handler](self, a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
				end
			else
				return orig(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
			end
		end
	else
		-- The handler is a function, just call it
		return function(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
			if module_.actives[orig] then
				if (pre_hooks == nil) then
					-- nil: pre_hooks
					handler(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
					return orig(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
				else
					-- true: post_hooks
					if (pre_hooks == true) then
						orig(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
					end
					return handler(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
				end
			else
				return orig(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
			end
		end
	end
end

--[[----------------------------------------------------------------------
	_getMethodHook - Internal Method
-------------------------------------------------------------------------]]
local function _getMethodHook(self, name, object, method, handler, orig, script, pre_hooks)
	local module_ = self.modules[name]
	if type(handler) == "string" then
		-- The handler is a method, need to self it
		if script then
			return function()
				if module_.actives[orig] and self[handler] then
					if (pre_hooks == nil) then
						-- nil: pre_hooks
						self[handler](self, object)
						return orig()
					else
						-- true: post_hooks
						if (pre_hooks == true) then
							orig()
						end
						return self[handler](self, object)
					end
				else
					return orig()
				end
			end
		else
			return function(obj, a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
				if module_.actives[orig] and self[handler] then
					if (pre_hooks == nil) then
						-- nil: pre_hooks
						self[handler](self, obj, a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
						return orig(obj, a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
					else
						-- true: post_hooks
						if (pre_hooks == true) then
							orig(obj, a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
						end
						return self[handler](self, obj, a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
					end
				else
					return orig(obj, a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
				end
			end
		end
	else
		-- The handler is a function, just call it
		if script then
			return function()
				if module_.actives[orig] then
					if (pre_hooks == nil) then
						-- nil: pre_hooks
						handler(object)
						return orig()
					else
						-- true: post_hooks
						if (pre_hooks == true) then
							orig()
						end
						return handler(object)
					end
				else
					return orig()
				end
			end
		else
			return function(obj, a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
				if module_.actives[orig] then
					if (pre_hooks == nil) then
						-- nil: pre_hooks
						handler(obj, a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
						return orig(obj, a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
					else
						-- true: post_hooks
						if (pre_hooks == true) then
							orig(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
						end
						return handler(obj, a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
					end
				else
					return orig(obj, a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
				end
			end
		end
	end
end

--[[----------------------------------------------------------------------
	zUI.hooklib.HookFunc - internal method.
	o You can only hook each function once from each source.
	o If there is an inactive hook for this func/handler pair, we reactivate it
	o If there is an inactive hook for another handler, we error out.
	o Looks for handler as a method of the calling class, error if not available
	o If handler is a function, it just uses it directly through the wrapper
-------------------------------------------------------------------------]]
local function _hookFunc(self, name, func, handler, pre_hooks)
	local orig_func = _G[func]
	if not orig_func or type(orig_func) ~= "function" then
		_debug(self, string.format("Attempt to hook a non-existant function %q", orig_func),3)
		return
	end

	if not handler then handler = func end

	if self.modules == nil then
		self.modules = {}
	end

	if self.modules[name] == nil then
		self.modules[name] = {}
		self.modules[name].hooks = new()
		self.modules[name].actives = {}
		self.modules[name].handlers = {}
		self.modules[name].funcs = {}
		self.modules[name].scripts = {}
	end

	local module_ = self.modules[name]
	if module_.hooks[func] then
		local orig = module_.hooks[func].orig
		-- We have an active hook from this source.  Don't multi-hook
		if module_.actives[orig] then
			_debug(self, string.format("%q already has an active hook from this source.", func))
			return
		end
		-- The hook is inactive, so reactivate it
		if module_.handlers[orig] == handler then
			module_.actives[orig] = true
			return
		else
			_error("There is a stale hook for %q can't hook or reactivate.", func)
		end
	end

	if type(handler) == "string" then
		--if type(self[handler]) ~= "function" then
		--	_error("Could not find the the handler %q when hooking function %q", handler, func)
		--end
	elseif type(handler) ~= "function" then
		_error("Could not find the handler you supplied when hooking %q", func)
	end

	local t = setmetatable(new(), origFuncMetatable)
	module_.hooks[func] = t
	t.orig = orig_func

	module_.actives[orig_func] = true
	module_.handlers[orig_func] = handler
	local newFunc = _getFunctionHook(self, name, func, handler, orig_func, pre_hooks)
	module_.funcs[orig_func] = newFunc

	_G[func] = newFunc
end

--[[----------------------------------------------------------------------
	zUI.hooklib.UnhookFunc - internal method
	o If you attempt to unhook a function that has never been hooked, or to unhook in a
	system that has never had a hook before, the system will error with a stack trace
	o If we own the global function, then put the original back in its place and remove
	all references to the Hooks[func] structure.
	o If we don't own the global function (we've been hooked) we deactivate the hook,
	forcing the handler to passthrough.
-------------------------------------------------------------------------]]
local function _unhookFunc(self, name, func)
	local module_ = self.modules[name]
	if (module_ == nil) then return end

	if not module_.hooks[func] or not module_.funcs[module_.hooks[func].orig] then
		_debug(self, string.format("Tried to unhook %q which is not currently hooked.", func))
		return
	end

	local orig = module_.hooks[func].orig

	if module_.actives[orig] then
		-- See if we own the global function
		if _G[func] == module_.funcs[orig] then
			_G[func] = orig
			module_.hooks[func] = del(module_.hooks[func])
			module_.handlers[orig] = nil
			module_.funcs[orig] = nil
			module_.scripts[orig] = nil
			module_.actives[orig] = nil
			-- Magically all-done
		else
			module_.actives[orig] = nil
		end
	end
end

--[[----------------------------------------------------------------------
	zUI.hooklib.HookMeth - Takes an optional fourth argument
	o script - Signifies whether this is a script hook or not
-------------------------------------------------------------------------]]
local function _hookMethod(self, name, obj, method, handler, script)
	if not handler then handler = method end
	if (not obj or type(obj) ~= "table") then
		_error("The object you supplied could not be found, or isn't a table.")
	end

	if self.modules == nil then
		self.modules = {}
	end

	if self.modules[name] == nil then
		self.modules[name] = {}
		self.modules[name].hooks = new()
		self.modules[name].actives = {}
		self.modules[name].handlers = {}
		self.modules[name].funcs = {}
		self.modules[name].scripts = {}
	end

	local module_ = self.modules[name]

	if module_.hooks[obj] and module_.hooks[obj][method] then
		local orig = module_.hooks[obj][method].orig
		-- We have an active hook from this source.  Don't multi-hook
		if module_.actives[orig] then
			_debug(self, string.format("%q already has an active hook from this source.", method))
			return
		end
		-- The hook is inactive, so reactivate it.
		if module_.handlers[orig] == handler then
			module_.actives[orig] = true
			return
		else
			_error("There is a stale hook for %q can't hook or reactivate.", method)
		end
	end
	-- We're clear to try the hook, let's make some checks first
	if type(handler) == "string" then
		--if type(self[handler]) ~= "function" then
		--	_error("Could not find the handler %q you supplied when hooking method %q", handler, method)
		--end
	elseif type(handler) ~= "function" then
		_error("Could not find the handler you supplied when hooking method %q", method)
	end
	-- Handler has been found, so now try to find the method we're trying to hook
	local orig
	-- Script
	if script then
		if not obj.GetScript then
			_error("The object you supplied does not have a GetScript method.")
		end
		if not obj:HasScript(method) then
			_error("The object you supplied doesn't allow the %q method.", method)
		end
		-- Sometimes there is not a original function for a script.
		orig = obj:GetScript(method)
		if not orig then
			orig = function() end
		end
		-- Method
	else
		orig = obj[method]
	end
	if not orig then
		_error("Could not find the method or script %q you are trying to hook.", method)
	end
	if not module_.hooks[obj] then
		module_.hooks[obj] = new()
	end
	local t = setmetatable(new(), origMethodMetatable)
	module_.hooks[obj][method] = t
	t.orig = orig

	module_.actives[orig] = true
	module_.handlers[orig] = handler
	module_.scripts[orig] = script and true or nil
	local newFunc = _getMethodHook(self, name, obj, method, handler, orig, script)
	module_.funcs[orig] = newFunc

	if script then
		obj:SetScript(method, newFunc)
	else
		obj[method] = newFunc
	end
end

--[[----------------------------------------------------------------------
	zUI.hooklib.UnhookMethod - Internal method
	o If you attempt to unhook a method that has never been hooked, or to unhook in a
	system that has never had a hook before, the system will error with a stack trace
	o If we own the global method, then put the original back in its place and remove
	all references to the Hooks[obj][method] structure.
	o If we don't own the global method (we've been hooked) we deactivate the hook,
	forcing the handler to passthrough.
-------------------------------------------------------------------------]]
local function _unhookMethod(self, name, obj, method)
	local module_ = self.modules[name]
	if (module_ == nil) then return end

	if not module_.hooks[obj] or not module_.hooks[obj][method] or not module_.funcs[module_.hooks[obj][method].orig] then
		_debug(self, string.format("Attempt to unhook a method %q that is not currently hooked.", method))
		return
	end

	local orig = module_.hooks[obj][method].orig

	if module_.actives[orig] then
		-- If this is a script
		if module_.scripts[orig] then
			if obj:GetScript(method) == module_.funcs[orig] then
				-- We own the script.  Kill it.
				obj:SetScript(method, orig)
				module_.hooks[obj][method] = del(module_.hooks[obj][method])
				module_.handlers[orig] = nil
				module_.funcs[orig] = nil
				module_.scripts[orig] = nil
				module_.actives[orig] = nil
			else
				module_.actives[orig] = nil
			end
		else
			if obj[method] == module_.funcs[orig] then
				-- We own the method.  Kill it.
				obj[method] = orig
				module_.hooks[obj][method] = del(module_.hooks[obj][method])
				module_.handlers[orig] = nil
				module_.funcs[orig] = nil
				module_.scripts[orig] = nil
				module_.actives[orig] = nil
			else
				module_.actives[orig] = nil
			end
		end
	end
	if not next(module_.hooks[obj]) then
		-- Spank the table
		module_.hooks[obj] = del(module_.hooks[obj])
	end
end

local function getTristateValue(val, default)
	if (val == nil) then
		return val
	elseif (type(val) == "boolean") then
		return (val ~= false)
	elseif (type(val) == "number") then
		if (val > 0) then
			return true
		elseif (val == 0) then
			return false
		else
			return nil
		end
	else
		return default
	end
end

--[[----------------------------------------------------------------------
	zUI.hooklib.HookFunc
	self:HookFunc("moduleName", "functionName", ["handlerName" | handler], [pre_hooks | post_hooks | no_callback])
	self:HookFunc("moduleName", ObjectName, "Method", ["Handler" | handler], [pre_hooks | post_hooks | no_callback])
-------------------------------------------------------------------------]]
function zUI.hooklib.HookFunc(name, arg1, arg2, arg3, arg4)
	local self = zUI.hooklib
	if type(arg1) == "string" then
		if protFuncs[arg1] then
			local module_ = self.modules[name]
 			if (module_ ~= nil) and (module_.name ~= nil) and (module_.name ~= "") then
				_error("%s tried to hook %q, which is a Blizzard protected function.", module_.name, arg1)
			else
				_debug(self, string.format("An Addon tried to hook %q, which is a Blizzard protected function.", arg1))
			end
		else
			-- nil: pre_hooks, true: post_hooks, false: no callback
			local pre_hooks = getTristateValue(arg3)
			_hookFunc(self, name, arg1, arg2, pre_hooks)
		end
	else
		-- nil: pre_hooks, true: post_hooks, false: no callback
		local pre_hooks = getTristateValue(arg4)
		_hookMethod(self, name, arg1, arg2, arg3, pre_hooks)
	end
end

--[[----------------------------------------------------------------------
	zUI.hooklib.HookScript
	self:HookScript("moduleName", ObjectName, "Method", ["Handler" | handler], [pre_hooks | post_hooks | no_callback])
-------------------------------------------------------------------------]]
function zUI.hooklib.HookScript(name, arg1, arg2, arg3, arg4)
	local self = zUI.hooklib
	-- nil: pre_hooks, true: post_hooks, false: no callback
	local pre_hooks = getTristateValue(arg4)
	_hookMethod(self, name, arg1, arg2, arg3, pre_hooks)
end

--[[----------------------------------------------------------------------
	zUI.hooklib.Unhook
	zUI.hooklib.Unhook("moduleName", "functionName")
	zUI.hooklib.Unhook("moduleName", ObjectName, "Method")
-------------------------------------------------------------------------]]
function zUI.hooklib.Unhook(name, arg1, arg2)
	local self = zUI.hooklib
	if type(arg1) == "string" then
		_unhookFunc(self, name, arg1)
	else
		_unhookMethod(self, name, arg1, arg2)
	end
end

--[[----------------------------------------------------------------------
	zUI.hooklib.UnhookAll("moduleName") - Unhooks all active hooks from the calling source
-------------------------------------------------------------------------]]
function zUI.hooklib.UnhookAll(name)
	local self = zUI.hooklib
	if name ~= nil and name ~= "" then
		local module_ = self.modules[name]
		if (module_ == nil) then return end

		if (module_.hooks ~= nil) then
			for key, value in pairs(module_.hooks) do
				if type(key) == "table" then
					for method in pairs(value) do
						zUI.hooklib.Unhook(name, key, method)
					end
				else
					zUI.hooklib.Unhook(name, key)
				end
			end
		end
	end
end

--[[----------------------------------------------------------------------
	zUI.hooklib.UnhookAllFull - Unhooks all active hooks from the calling source
-------------------------------------------------------------------------]]
function zUI.hooklib.UnhookAllFull()
	local self = zUI.hooklib
	if self.modules ~= nil then
		for i, name in pairs(self.modules) do
			zUI.hooklib.UnhookAll(name)
		end
	end
end

--[[----------------------------------------------------------------------
	zUI.hooklib.IsHooked()
	self:IsHooked("functionName")
	self:IsHooked(ObjectName, "Method")

	Returns whether or not the given function is hooked in the current
	namespace.  A hooked, but inactive function is considered NOT
	hooked in this context.
-------------------------------------------------------------------------]]
function zUI.hooklib.IsHooked(name, obj, method)
	local self = zUI.hooklib
	local module_ = self.modules[name]
	if (module_ ~= nil) then
		if method and obj then
			if module_.hooks and module_.hooks[obj] and module_.hooks[obj][method] and module_.actives[module_.hooks[obj][method].orig] then
				return true, module_.handlers[module_.hooks[obj][method].orig]
			end
		else
			if module_.hooks and module_.hooks[obj] and module_.actives[module_.hooks[obj].orig] then
				return true, module_.handlers[module_.hooks[obj].orig]
			end
		end
	end
	return false, nil
end

--[[----------------------------------------------------------------------
	zUI.hooklib.HookCallback()
	self:HookCallback("functionName")
	self:HookCallback(ObjectName, "Method")

	Returns whether or not the given function is hooked in the current
	namespace.  A hooked, but inactive function is considered NOT
	hooked in this context.
-------------------------------------------------------------------------]]
function zUI.hooklib.HookCallback(name, obj, method)
	local self = zUI.hooklib
	local module_ = self.modules[name]
	if (module_ ~= nil) then
		if method and obj then
			if module_.hooks and module_.hooks[obj] and module_.hooks[obj][method] and module_.actives[module_.hooks[obj][method].orig] then
				return true, module_.hooks[obj][method]
			end
		else
			if module_.hooks and module_.hooks[obj] and module_.actives[module_.hooks[obj].orig] then
				return true, module_.hooks[obj]
			end
		end
	end
	return false, nil
end

--[[----------------------------------------------------------------------
	zUI.hooklib.HookReport - Lists registered hooks from this source
-------------------------------------------------------------------------]]

function zUI.hooklib.HookReport(name)
	local self = zUI.hooklib
	_debug(self, "This is a list of all active hooks for this object:")

	local module_ = self.modules[name]
	if (not module_) or (not module_.hooks) then _debug(self, "No registered hooks.") return end

	for key, value in pairs(module_.hooks) do
		if type(value) == "table" then
			for method in pairs(value) do
				_debug(self, string.format("key: %s method: %q |cff%s|r", tostring(key), method, module_.hooks[key][method].active and "00ff00Active" or "ffff00Inactive"))
			end
		else
			_debug(self, string.format("key: %s value: %q |cff%s|r", tostring(key), tostring(value), module_.hooks[key].active and "00ff00Active" or "ffff00Inactive"))
		end
	end
end

--[[---------------------------------------------------------------------------------
	Stub and Library registration
----------------------------------------------------------------------------------]]

function zUI.hooklib.InitModule(mod, name)
	local self = zUI.hooklib
	if (self.modules == nil) then
		self.modules[mod] = {}
		if name ~= nil and name ~= "" then
			self.modules[mod].name = name
		else
			self.modules[mod].name = mod
		end
		self.modules[mod].hooks = new()
		self.modules[mod].actives = {}
		self.modules[mod].handlers = {}
		self.modules[mod].funcs = {}
		self.modules[mod].scripts = {}
	end
end

function zUI_UseAction(slot, type, onSelf)
	print("slot = "..slot..", type = "..tostring(type))
	--[[
	local isHooked, callback = zUI.hooklib.HookCallback("zUI", "UseAction")
	if isHooked and callback then
		callback(slot, type, onSelf)
	end
	--]]
end

function zUI_hooklib_test()
	zUI.hooklib.HookFunc("zUI", "UseAction", zUI_UseAction)
end

zUI.hooklib.InitModule("zUI")
--zUI_hooklib_test()
